#pragma once

#include "base/allocation.h"
#include "utility/vector.h"

#include <stdarg.h>

namespace l8
{

// OS-dependent routines
class OS : public AllStatic
{
public:
    // Initializes the platform OS support. Called once at VM startup.
    static void Setup();

    // Returns the accumulated user time for thread. This routine
    // can be used for profiling. The implementation should
    // strive for high-precision timer resolution, preferable
    // micro-second resolution.
    static int GetUserTime(uint32_t* secs,  uint32_t* usecs);

    // Get a tick counter normalized to one tick per microsecond.
    // Used for calculating time intervals.
    static int64_t Ticks();

    // Allocate/Free memory used by l8 heap. Pages are readable/writable, but
    // they are not guaranteed to be executable unless 'executable' is true.
    // Returns the address of allocated memory, or NULL if failed.
    static void* Allocate(const size_t requested, size_t* allocated, bool is_executable);

    static void Free(void* address, const size_t size);

    // Get the Alignment guaranteed by Allocate().
    static size_t AllocateAlignment();

#ifdef ENABLE_HEAP_PROTECTION
    // Protect/unprotect a block of memory by marking it read-only/writable.
    static void Protect(void* address, size_t size);
    static void Unprotect(void* address, size_t size, bool is_executable);
#endif

    // Returns an indication of whether a pointer is in a space that
    // has been allocated by Allocate().  This method may conservatively
    // always return false, but giving more accurate information may
    // improve the robustness of the stack dump code in the presence of
    // heap corruption.
    static bool IsOutsideAllocatedSpace(void* pointer);

    // Sleep for a number of milliseconds.
    static void Sleep(const int milliseconds);

    // Abort the current process.
    static void Abort();

    // Debug break.
    static void DebugBreak();

    // Safe formatting print. Ensures that str is always null-terminated.
    // Returns the number of chars written, or -1 if output was truncated.
    static int SNPrintF(Vector<char> str, const char* format, ...);
    static int VSNPrintF(Vector<char> str,
                         const char* format,
                         va_list args);
    static void PrintF(const char * format, ...);

    // Walk the stack.
    static const int kStackWalkError = -1;
    static const int kStackWalkMaxNameLen = 256;
    static const int kStackWalkMaxTextLen = 256;
    struct StackFrame
    {
        void* address;
        char text[kStackWalkMaxTextLen];
    };

    static int StackWalk(Vector<StackFrame> frames);

private:
    DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
};

} // namespace l8
